home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-02-20 | 11.9 KB | 364 lines | [TEXT/CWIE] |
-
- #include "ScriptableDBDocument.h"
-
- #include "HFSBackingStore.h"
- #include "DBElementToken.h"
- #include "Application.h"
-
- #include "DBRecord.h"
- #include "DBElement.h"
- #include "DBProperty.h"
- #include "DataRecord.h"
-
- #include "Exceptions.h"
-
- #include <AppleEvents.h>
- #include <AERegistry.h>
- #include <ASRegistry.h>
-
- TScriptableDBDocument* gScriptableDocumentList = nil;
-
- TPropertyDescription TScriptableDBDocument::fPropertiesOfClass[] = {
- { pIsModified, 0, typeBoolean, typeBoolean }
- };
-
- #pragma segment ObjectResident
- ImplementClassData(TScriptableDBDocument, clScriptableDBDocument);
-
- //--------------------------------------------------------------------------------
- // TScriptableDBDocument::~TScriptableDBDocument
- //--------------------------------------------------------------------------------
- TScriptableDBDocument::~TScriptableDBDocument()
- {
- //
- // Save changes before going away. Generally speaking, it's bad
- // to do things like this in the destructor. It's far better to
- // have a Dispose() method that calls all of the methods such as
- // 'save' that may need to be called, and then does a 'delete this'.
- // That way, derived classes can override methods called from the
- // destructor and they will still be called.
- //
- this->Save();
- }
-
- //--------------------------------------------------------------------------------
- // TScriptableDBDocument::NewDatabase
- //--------------------------------------------------------------------------------
- TScriptableDBDocument* TScriptableDBDocument::NewDatabase()
- {
- TScriptableDBDocument* newDatabase = new TScriptableDBDocument();
-
- return newDatabase;
- }
-
- //--------------------------------------------------------------------------------
- // TScriptableDBDocument::OpenDatabase
- //--------------------------------------------------------------------------------
- TScriptableDBDocument* TScriptableDBDocument::OpenDatabase(TFSSpecification& fileSpec)
- {
- THFSBackingStore* backingStore = new THFSBackingStore(fileSpec);
- TScriptableDBDocument* openDatabase = new TScriptableDBDocument(backingStore);
-
- return openDatabase;
- }
-
- //--------------------------------------------------------------------------------
- // TScriptableDBDocument::OpenDatabase
- //--------------------------------------------------------------------------------
- TScriptableDBDocument* TScriptableDBDocument::OpenDatabase(TFSSpecification& fileSpec, Int64 requiredDocumentID)
- {
- TScriptableDBDocument* foundDatabase = nil;
-
- //
- // First, test to see if the database is already open.
- // If so, we don't want to open it again.
- //
- TAbstractDocument* openDatabase = TApplication::Instance()->FindDocument(fileSpec);
- if(openDatabase != nil)
- {
- //
- // Only downcast if the document type is correct
- //
- if((openDatabase->DerivedFrom(clScriptableDBDocument)) && (openDatabase->DocumentIdentifier() == requiredDocumentID))
- foundDatabase = (TScriptableDBDocument*)openDatabase;
- }
- //
- // If the database wasn't open, then open it and check to
- // see if its document ID matches.
- //
- else
- {
- foundDatabase = TScriptableDBDocument::OpenDatabase(fileSpec);
- if(foundDatabase != nil)
- {
- //
- // If we don't really want to open this database
- // (we're searching for a database with a different
- // document ID), then close and delete it
- //
- if(foundDatabase->DocumentIdentifier() != requiredDocumentID)
- {
- delete foundDatabase;
- foundDatabase = nil;
- }
- }
- }
-
- return foundDatabase;
- }
-
- //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
- // Overrides of class TDatabaseDocument
- //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
-
- //--------------------------------------------------------------------------------
- // TScriptableDBDocument::DocumentIdentifier
- //--------------------------------------------------------------------------------
- Int64 TScriptableDBDocument::DocumentIdentifier() const
- {
- return TDatabaseDocument::ObjectsKeySpace();
- }
-
- //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
- // Overrides of class TAbstractDocument
- //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
-
- //----------------------------------------------------------------------------------------
- // TScriptableDBDocument::DocumentFSSpecification
- //
- // Return the FSSpec for the file this document is saved in, if any.
- //----------------------------------------------------------------------------------------
- Boolean TScriptableDBDocument::DocumentFSSpecification(TFSSpecification& fileSpec) const
- {
- TAbstractBackingStore* backingStore = this->GetBackingStore();
- Boolean hasFSSpec = false;
-
- if((backingStore != nil) && (backingStore->BackingStoreType() == kHFSBackingStore))
- {
- fileSpec = ((THFSBackingStore*)backingStore)->FileSpec();
- hasFSSpec = true;
- }
-
- return hasFSSpec;
- }
-
- //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
- // Overrides of class TAbstractScriptableObject
- //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
-
- //--------------------------------------------------------------------------------
- // TScriptableDBDocument::GetProperty
- //--------------------------------------------------------------------------------
- TDescriptor TScriptableDBDocument::GetProperty(const TAETransaction& t, DescType propertyName, DescType desiredType, unsigned long additionalInfo /*= 0*/)
- {
- TDescriptor result;
-
- switch(propertyName)
- {
- case pName:
- {
- //
- // This fixed-length storage isn't too desirable.
- // We should call DocumentName with a tiny TUpdateDataReference
- // just to find out how long the name is, then preallocate
- // a handle to copy the whole data into.
- //
- // This method is good enough, though, because we know
- // that filenames are never anywhere close to 255 characters long.
- //
- char nameStorage[256];
- TUpdataDataReference name(typeChar, nameStorage, 0, 256);
- this->DocumentName(name);
- result.SetDescriptorData(name);
- break;
- }
-
- case pID:
- {
- result.SetSInt64Data(this->DocumentIdentifier());
- break;
- }
-
- case pIndex:
- {
- result.SetSInt32Data(TApplication::Instance()->DocumentIndex(this->DocumentIdentifier()));
- break;
- }
-
- case pIsModified:
- {
- result.SetBooleanData(this->DocumentNeedsSave());
- break;
- }
-
- default:
- {
- result = Inherited::GetProperty(t, propertyName, desiredType, additionalInfo);
- break;
- }
- }
-
- return result;
- }
-
- //--------------------------------------------------------------------------------
- // TScriptableDBDocument::SetProperty
- //--------------------------------------------------------------------------------
- void TScriptableDBDocument::SetProperty(const TAETransaction& t, DescType propertyName, TDescriptor& data, unsigned long additionalInfo /*= 0*/)
- {
- Inherited::SetProperty(t, propertyName, data, additionalInfo);
- }
-
- //--------------------------------------------------------------------------------
- // TScriptableDBDocument::MakeKeyDataForSelf
- //--------------------------------------------------------------------------------
- void TScriptableDBDocument::MakeKeyDataForSelf(const TAETransaction& t, DescType& keyForm, TDescriptor& keyData)
- {
- //
- // If this document can be saved, then it has a name.
- //
- if(this->CanSaveDocument())
- {
- Inherited::MakeKeyDataForSelf(t, keyForm, keyData);
- }
- //
- // If we don't have a name, then use our ID
- //
- else
- {
- keyForm = formUniqueID;
- keyData = this->GetProperty(t, pID, typeWildCard, 0); // •••
- }
- }
-
- //--------------------------------------------------------------------------------
- // TScriptableDBDocument::AECommand
- //--------------------------------------------------------------------------------
- TDescriptor TScriptableDBDocument::AECommand(const TAETransaction& t, long aeCommandID, TAbstractScriptableObject* auxObjects /*= nil*/, long auxInfo /*= 0*/)
- {
- TDescriptor result;
-
- switch(aeCommandID)
- {
- case kAESave:
- {
- //
- // If the event specified a "save in" parameter, then
- // do a save-as. Otherwise, just save.
- //
- TDescriptor saveInFile = t.Message().GetOptionalParameter(keyAEFile);
- if(saveInFile.IsNullDescriptor() == true)
- {
- //
- // ••• n.b. Currently, 'save' will silently fail
- // if no file has been specified. We can test for
- // this situation by calling this->CanSaveDocument.
- // Should we fail, or make an arbitrary file in
- // the temp items folder, or...
- //
- this->Save();
- }
- else
- {
- //
- // Make sure that the file is created when it
- // is converted from a TDescriptor to a TFSSpecification
- //
- TFSSpecification saveInFSSpec(saveInFile, kForceFileCreation, kDBCreator, kDBType);
- this->SaveAs(saveInFSSpec);
- }
-
- result = this->BuildObjectSpecifier(t);
- break;
- }
-
- case kAEClose:
- {
- //
- // Close can be pretty dangerous if we're multithreaded
- // and some other thread is working with this document.
- // Therefore, we will close this document later.
- //
- this->Save();
- TApplication::Instance()->MarkForClose(this);
- result = this->BuildObjectSpecifier(t);
- break;
- }
-
- default:
- {
- result = Inherited::AECommand(t, aeCommandID, auxObjects, auxInfo);
- break;
- }
- }
-
- return result;
- }
-
- //--------------------------------------------------------------------------------
- // TScriptableDBDocument::CreateNewElement
- //--------------------------------------------------------------------------------
- TAbstractScriptableObject* TScriptableDBDocument::CreateNewElement(const TAETransaction& t, DescType newObjectClass, TDescriptor initialData, TDescriptor initialProperties, Boolean& usedInitialData, Boolean& usedInitialProperties)
- {
- return Inherited::CreateNewElement(t, newObjectClass, initialData, initialProperties, usedInitialData, usedInitialProperties);
- }
-
- //----------------------------------------------------------------------------------------
- // TScriptableDBDocument::RepresentativeScriptingObject
- //
- // The representative can provide properties for the document.
- // All commands identified by SendCommandToRepresentative are also sent to the
- // representative
- //----------------------------------------------------------------------------------------
- TAbstractScriptableObject* TScriptableDBDocument::RepresentativeScriptingObject(const TAETransaction&)
- {
- return new TDBElementToken(this->GetMetaRoot());
- }
-
- //----------------------------------------------------------------------------------------
- // TScriptableDBDocument::SendCommandToRepresentative
- //----------------------------------------------------------------------------------------
- Boolean TScriptableDBDocument::SendCommandToRepresentative(const TAETransaction& t, long aeCommandID)
- {
- if((aeCommandID == kAESave) || (aeCommandID == kAEClose))
- return false;
-
- return Inherited::SendCommandToRepresentative(t, aeCommandID);
- } // TScriptableDBDocument::SendCommandToRepresentative
-
- //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
- // Methods of TScriptableDBDocument
- //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
-
- //--------------------------------------------------------------------------------
- // TScriptableDBDocument::SaveAs
- //--------------------------------------------------------------------------------
- void TScriptableDBDocument::SaveAs(TFSSpecification& fileSpec)
- {
- TFSSpecification currentSpecification;
- Boolean hasSpec = this->DocumentFSSpecification(currentSpecification);
-
- //
- // Is the parameter to "Save As" the same as the specification
- // already stored in our backing-store object? If so, just
- // save, and don't mess with save-as.
- //
- if(hasSpec && (currentSpecification == fileSpec))
- {
- this->Save();
- }
- else
- {
- //
- // Create a backing store object to save the database into
- // and call SetBackingStore to set up and save the file.
- //
- // ◊Question: If we already have a backing-store object,
- // should we delete its file?
- //
- THFSBackingStore* backingStore = new THFSBackingStore(fileSpec, kDBCreator, kDBType);
- this->SetBackingStore(backingStore);
- }
- }
-
-